@@ -7,6 +7,8 @@ services: |
||
| 7 | 7 |
env: |
| 8 | 8 |
global: |
| 9 | 9 |
- APP_SECRET_TOKEN=b2724973fd81c2f4ac0f92ac48eb3f0152c4a11824c122bcf783419a4c51d8b9bba81c8ba6a66c7de599677c7f486242cf819775c433908e77c739c5c8ae118d |
| 10 |
+ - RSPEC_TASK=spec:nofeatures |
|
| 11 |
+ - COVERALLS_PARALLEL=true |
|
| 10 | 12 |
- secure: fzmSI7PQz6CJiIJNAtLAuy3TMmYCrK4bUil3uufh8JkHfpSGWOZt2i6fZ8yZ7pzwG5Aw7eZDgdFsNcEPJlgUDJhlwjg+QxCJslhotTQ9qI3Ieo85peWlU9dZFTOZcrCu0net/hY2FE4ZpTRb5r8A/DRv9ukA8P8tShhePCjckgg= |
| 11 | 13 |
- secure: YjW07LpRSiC9xB6PhLQ4LVv2VphvF3IacV43PLfvzdagjy14yAwKXTUlSadgRaMbndB2dlCTe3YcY11a/xtX/2HDrF14NHPXQdL7e2dJUS3CDLSKZK26x1SOiaaDIrl1jO1xr5kOUd+564MAcNUzDTJQR4CrWl/5t6EwW4iYQVc= |
| 12 | 14 |
- secure: RJiSTB9Anax6uL6mgYY1m42w71ohlsfIlVCk7ho6W19ZfSzQOfom0mBdeNwfgmXsMMnvnqatfxSg8k3C//pRtI/tjzAovHd7t1YIN1IkDNf9uSpzrIeXXc4fSHaVxnl512oI/eBQy9MSBjVZjrg5XEzLKKEGsZCai+ZKB4PS+nM= |
@@ -15,17 +17,22 @@ env: |
||
| 15 | 17 |
- DATABASE_ADAPTER=postgresql DATABASE_USERNAME=postgres |
| 16 | 18 |
- DOCKER_IMAGE=cantino/huginn-single-process DOCKERFILE=docker/single-process/Dockerfile |
| 17 | 19 |
- DOCKER_IMAGE=cantino/huginn DOCKERFILE=docker/multi-process/Dockerfile |
| 20 |
+ - RSPEC_TASK=spec:features |
|
| 18 | 21 |
matrix: |
| 19 | 22 |
exclude: |
| 20 | 23 |
- env: DOCKER_IMAGE=cantino/huginn-single-process DOCKERFILE=docker/single-process/Dockerfile |
| 21 | 24 |
- env: DOCKER_IMAGE=cantino/huginn DOCKERFILE=docker/multi-process/Dockerfile |
| 25 |
+ - env: RSPEC_TASK=spec:features |
|
| 22 | 26 |
include: |
| 23 | 27 |
- rvm: 2.3.0 |
| 24 | 28 |
env: DATABASE_ADAPTER=mysql2 DOCKER_IMAGE=cantino/huginn-single-process DOCKERFILE=docker/single-process/Dockerfile |
| 25 | 29 |
- rvm: 2.3.0 |
| 26 | 30 |
env: DATABASE_ADAPTER=mysql2 DOCKER_IMAGE=cantino/huginn DOCKERFILE=docker/multi-process/Dockerfile |
| 31 |
+ - rvm: 2.3.0 |
|
| 32 |
+ env: RSPEC_TASK=spec:features DATABASE_ADAPTER=mysql2 |
|
| 33 |
+ - rvm: 2.3.0 |
|
| 34 |
+ env: RSPEC_TASK=spec:features DATABASE_ADAPTER=postgresql DATABASE_USERNAME=postgres |
|
| 27 | 35 |
rvm: |
| 28 |
-- 2.0.0 |
|
| 29 | 36 |
- 2.1 |
| 30 | 37 |
- 2.2 |
| 31 | 38 |
- 2.3.0 |
@@ -35,7 +42,8 @@ before_install: |
||
| 35 | 42 |
- sudo apt-get -qq update |
| 36 | 43 |
- sudo apt-get install -y mysql-server |
| 37 | 44 |
script: |
| 38 |
- - if [ -z "${DOCKER_IMAGE}" ]; then bundle exec rake db:create db:migrate && bundle exec rake; else ./build_docker_image.sh; fi
|
|
| 45 |
+ - if [ -z "${DOCKER_IMAGE}" ]; then bundle exec rake db:create db:migrate; else true; fi
|
|
| 46 |
+ - if [ -z "${DOCKER_IMAGE}" ]; then bundle exec rake $RSPEC_TASK; else ./build_docker_image.sh; fi
|
|
| 39 | 47 |
notifications: |
| 40 | 48 |
irc: |
| 41 | 49 |
channels: |
@@ -44,9 +52,4 @@ notifications: |
||
| 44 | 52 |
- "<%{author}> %{branch} - %{commit} (%{commit_message}): %{message}"
|
| 45 | 53 |
- 'Change view : %{compare_url}'
|
| 46 | 54 |
- 'Build details : %{build_url}'
|
| 47 |
- webhooks: |
|
| 48 |
- urls: |
|
| 49 |
- - https://webhooks.gitter.im/e/5f92cc0393c6f1defe0d |
|
| 50 |
- on_success: change # options: [always|never|change] default: always |
|
| 51 |
- on_failure: always # options: [always|never|change] default: always |
|
| 52 |
- on_start: never # options: [always|never|change] default: never |
|
| 55 |
+ webhooks: https://coveralls.io/webhook?repo_token=COVERALLS_REPO_TOKEN |
@@ -141,7 +141,7 @@ group :development do |
||
| 141 | 141 |
end |
| 142 | 142 |
|
| 143 | 143 |
group :test do |
| 144 |
- gem 'coveralls', require: false |
|
| 144 |
+ gem 'coveralls', '~> 0.7.4', require: false |
|
| 145 | 145 |
gem 'capybara-select2', require: false |
| 146 | 146 |
gem 'delorean' |
| 147 | 147 |
gem 'poltergeist' |
@@ -155,6 +155,7 @@ group :development do |
||
| 155 | 155 |
gem 'shoulda-matchers' |
| 156 | 156 |
gem 'vcr' |
| 157 | 157 |
gem 'webmock', '~> 1.17.4', require: false |
| 158 |
+ gem 'database_cleaner', '~> 1.5.3' |
|
| 158 | 159 |
end |
| 159 | 160 |
end |
| 160 | 161 |
|
@@ -157,15 +157,16 @@ GEM |
||
| 157 | 157 |
colorize (0.7.7) |
| 158 | 158 |
concurrent-ruby (1.0.1) |
| 159 | 159 |
cookiejar (0.3.2) |
| 160 |
- coveralls (0.7.1) |
|
| 161 |
- multi_json (~> 1.3) |
|
| 162 |
- rest-client |
|
| 163 |
- simplecov (>= 0.7) |
|
| 164 |
- term-ansicolor |
|
| 165 |
- thor |
|
| 160 |
+ coveralls (0.7.12) |
|
| 161 |
+ multi_json (~> 1.10) |
|
| 162 |
+ rest-client (>= 1.6.8, < 2) |
|
| 163 |
+ simplecov (~> 0.9.1) |
|
| 164 |
+ term-ansicolor (~> 1.3) |
|
| 165 |
+ thor (~> 0.19.1) |
|
| 166 | 166 |
crack (0.4.2) |
| 167 | 167 |
safe_yaml (~> 1.0.0) |
| 168 | 168 |
daemons (1.1.9) |
| 169 |
+ database_cleaner (1.5.3) |
|
| 169 | 170 |
debug_inspector (0.0.2) |
| 170 | 171 |
delayed_job (4.1.1) |
| 171 | 172 |
activesupport (>= 3.0, < 5.0) |
@@ -522,7 +523,7 @@ GEM |
||
| 522 | 523 |
net-ssh (>= 2.8.0) |
| 523 | 524 |
string-scrub (0.0.5) |
| 524 | 525 |
systemu (2.6.4) |
| 525 |
- term-ansicolor (1.3.0) |
|
| 526 |
+ term-ansicolor (1.3.2) |
|
| 526 | 527 |
tins (~> 1.0) |
| 527 | 528 |
therubyracer (0.12.2) |
| 528 | 529 |
libv8 (~> 3.16.14.0) |
@@ -530,7 +531,7 @@ GEM |
||
| 530 | 531 |
thor (0.19.1) |
| 531 | 532 |
thread_safe (0.3.5) |
| 532 | 533 |
tilt (1.4.1) |
| 533 |
- tins (1.3.2) |
|
| 534 |
+ tins (1.10.1) |
|
| 534 | 535 |
treetop (1.5.3) |
| 535 | 536 |
polyglot (~> 0.3) |
| 536 | 537 |
twilio-ruby (3.11.6) |
@@ -597,8 +598,9 @@ DEPENDENCIES |
||
| 597 | 598 |
capistrano-rails (~> 1.1) |
| 598 | 599 |
capybara-select2 |
| 599 | 600 |
coffee-rails (~> 4.1.1) |
| 600 |
- coveralls |
|
| 601 |
+ coveralls (~> 0.7.4) |
|
| 601 | 602 |
daemons (~> 1.1.9) |
| 603 |
+ database_cleaner (~> 1.5.3) |
|
| 602 | 604 |
delayed_job (~> 4.1.0) |
| 603 | 605 |
delayed_job_active_record! |
| 604 | 606 |
delorean |
@@ -16,6 +16,12 @@ $ -> |
||
| 16 | 16 |
# Select2 Selects |
| 17 | 17 |
$(".select2").select2(width: 'resolve')
|
| 18 | 18 |
|
| 19 |
+ $(".select2-linked-tags").select2(
|
|
| 20 |
+ width: 'resolve', |
|
| 21 |
+ formatSelection: (obj) -> |
|
| 22 |
+ "<a href=\"#{this.element.data('urlPrefix')}/#{obj.id}/edit\" onClick=\"Utils.select2TagClickHandler(event, this)\">#{Utils.escape(obj.text)}</a>"
|
|
| 23 |
+ ) |
|
| 24 |
+ |
|
| 19 | 25 |
# Helper for selecting text when clicked |
| 20 | 26 |
$('.selectable-text').each ->
|
| 21 | 27 |
$(this).click -> |
@@ -132,3 +132,32 @@ class @Utils |
||
| 132 | 132 |
.fail (xhr, status, error) -> |
| 133 | 133 |
alert('Error: ' + error)
|
| 134 | 134 |
callback() |
| 135 |
+ |
|
| 136 |
+ @select2TagClickHandler: (e, elem) -> |
|
| 137 |
+ if e.which == 1 |
|
| 138 |
+ window.location = $(elem).attr('href')
|
|
| 139 |
+ else |
|
| 140 |
+ window.open($(elem).attr('href'))
|
|
| 141 |
+ |
|
| 142 |
+ # _.escape from underscore: https://github.com/jashkenas/underscore/blob/1e68f06610fa4ecb7f2c45d1eb2ad0173d6a2cc1/underscore.js#L1411-L1436 |
|
| 143 |
+ escapeMap = |
|
| 144 |
+ '&': '&' |
|
| 145 |
+ '<': '<' |
|
| 146 |
+ '>': '>' |
|
| 147 |
+ '"': '"' |
|
| 148 |
+ '\'': ''' |
|
| 149 |
+ '`': '`' |
|
| 150 |
+ |
|
| 151 |
+ createEscaper = (map) -> |
|
| 152 |
+ escaper = (match) -> |
|
| 153 |
+ map[match] |
|
| 154 |
+ |
|
| 155 |
+ # Regexes for identifying a key that needs to be escaped. |
|
| 156 |
+ source = '(?:' + Object.keys(map).join('|') + ')'
|
|
| 157 |
+ testRegexp = RegExp(source) |
|
| 158 |
+ replaceRegexp = RegExp(source, 'g') |
|
| 159 |
+ (string) -> |
|
| 160 |
+ string = if string == null then '' else '' + string |
|
| 161 |
+ if testRegexp.test(string) then string.replace(replaceRegexp, escaper) else string |
|
| 162 |
+ |
|
| 163 |
+ @escape = createEscaper(escapeMap) |
@@ -13,6 +13,15 @@ class @AgentEditPage |
||
| 13 | 13 |
e.preventDefault() |
| 14 | 14 |
alert 'Sorry, there appears to be an error in your JSON input. Please fix it before continuing.' |
| 15 | 15 |
|
| 16 |
+ if $(".link-region").length && $(".link-region").data("can-receive-events") == false
|
|
| 17 |
+ $(".link-region .select2-linked-tags option:selected").removeAttr('selected')
|
|
| 18 |
+ |
|
| 19 |
+ if $(".control-link-region").length && $(".control-link-region").data("can-control-other-agents") == false
|
|
| 20 |
+ $(".control-link-region .select2-linked-tags option:selected").removeAttr('selected')
|
|
| 21 |
+ |
|
| 22 |
+ if $(".event-related-region").length && $(".event-related-region").data("can-create-events") == false
|
|
| 23 |
+ $(".event-related-region .select2-linked-tags option:selected").removeAttr('selected')
|
|
| 24 |
+ |
|
| 16 | 25 |
$("#agent_name").each ->
|
| 17 | 26 |
# Select the number suffix if this is a cloned agent. |
| 18 | 27 |
if matches = this.value.match(/ \(\d+\)$/) |
@@ -103,24 +112,32 @@ class @AgentEditPage |
||
| 103 | 112 |
$(".link-region .select2-container").hide()
|
| 104 | 113 |
$(".link-region .propagate-immediately").hide()
|
| 105 | 114 |
$(".link-region .cannot-receive-events").show()
|
| 115 |
+ $(".link-region").data("can-receive-events", false)
|
|
| 106 | 116 |
|
| 107 | 117 |
showLinks: -> |
| 108 | 118 |
$(".link-region .select2-container").show()
|
| 109 | 119 |
$(".link-region .propagate-immediately").show()
|
| 110 | 120 |
$(".link-region .cannot-receive-events").hide()
|
| 121 |
+ $(".link-region").data("can-receive-events", true)
|
|
| 111 | 122 |
@showEventDescriptions() |
| 112 | 123 |
|
| 113 | 124 |
hideControlLinks: -> |
| 114 | 125 |
$(".control-link-region").hide()
|
| 126 |
+ $(".control-link-region").data("can-control-other-agents", false)
|
|
| 115 | 127 |
|
| 116 | 128 |
showControlLinks: -> |
| 117 | 129 |
$(".control-link-region").show()
|
| 130 |
+ $(".control-link-region").data("can-control-other-agents", true)
|
|
| 118 | 131 |
|
| 119 | 132 |
hideEventCreation: -> |
| 120 |
- $(".event-related-region").hide()
|
|
| 133 |
+ $(".event-related-region .select2-container").hide()
|
|
| 134 |
+ $(".event-related-region .cannot-create-events").show()
|
|
| 135 |
+ $(".event-related-region").data("can-create-events", false)
|
|
| 121 | 136 |
|
| 122 | 137 |
showEventCreation: -> |
| 123 |
- $(".event-related-region").show()
|
|
| 138 |
+ $(".event-related-region .select2-container").show()
|
|
| 139 |
+ $(".event-related-region .cannot-create-events").hide()
|
|
| 140 |
+ $(".event-related-region").data("can-create-events", true)
|
|
| 124 | 141 |
|
| 125 | 142 |
showEventDescriptions: -> |
| 126 | 143 |
if $("#agent_source_ids").val()
|
@@ -24,16 +24,17 @@ class Agent < ActiveRecord::Base |
||
| 24 | 24 |
|
| 25 | 25 |
EVENT_RETENTION_SCHEDULES = [["Forever", 0], ['1 hour', 1.hour], ['6 hours', 6.hours], ["1 day", 1.day], *([2, 3, 4, 5, 7, 14, 21, 30, 45, 90, 180, 365].map {|n| ["#{n} days", n.days] })]
|
| 26 | 26 |
|
| 27 |
- attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately, :drop_pending_events |
|
| 27 |
+ attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :receiver_ids, :scenario_ids, :keep_events_for, :propagate_immediately, :drop_pending_events |
|
| 28 | 28 |
|
| 29 | 29 |
json_serialize :options, :memory |
| 30 | 30 |
|
| 31 | 31 |
validates_presence_of :name, :user |
| 32 | 32 |
validates_inclusion_of :keep_events_for, :in => EVENT_RETENTION_SCHEDULES.map(&:last) |
| 33 |
- validate :sources_are_owned |
|
| 34 |
- validate :controllers_are_owned |
|
| 35 |
- validate :control_targets_are_owned |
|
| 36 |
- validate :scenarios_are_owned |
|
| 33 |
+ validates :sources, owned_by: :user_id |
|
| 34 |
+ validates :receivers, owned_by: :user_id |
|
| 35 |
+ validates :controllers, owned_by: :user_id |
|
| 36 |
+ validates :control_targets, owned_by: :user_id |
|
| 37 |
+ validates :scenarios, owned_by: :user_id |
|
| 37 | 38 |
validate :validate_schedule |
| 38 | 39 |
validate :validate_options |
| 39 | 40 |
|
@@ -267,22 +268,6 @@ class Agent < ActiveRecord::Base |
||
| 267 | 268 |
|
| 268 | 269 |
private |
| 269 | 270 |
|
| 270 |
- def sources_are_owned |
|
| 271 |
- errors.add(:sources, "must be owned by you") unless sources.all? {|s| s.user_id == user_id }
|
|
| 272 |
- end |
|
| 273 |
- |
|
| 274 |
- def controllers_are_owned |
|
| 275 |
- errors.add(:controllers, "must be owned by you") unless controllers.all? {|s| s.user_id == user_id }
|
|
| 276 |
- end |
|
| 277 |
- |
|
| 278 |
- def control_targets_are_owned |
|
| 279 |
- errors.add(:control_targets, "must be owned by you") unless control_targets.all? {|s| s.user_id == user_id }
|
|
| 280 |
- end |
|
| 281 |
- |
|
| 282 |
- def scenarios_are_owned |
|
| 283 |
- errors.add(:scenarios, "must be owned by you") unless scenarios.all? {|s| s.user_id == user_id }
|
|
| 284 |
- end |
|
| 285 |
- |
|
| 286 | 271 |
def validate_schedule |
| 287 | 272 |
unless cannot_be_scheduled? |
| 288 | 273 |
errors.add(:schedule, "is not a valid schedule") unless SCHEDULES.include?(schedule.to_s) |
@@ -0,0 +1,6 @@ |
||
| 1 |
+class OwnedByValidator < ActiveModel::EachValidator |
|
| 2 |
+ def validate_each(record, attribute, association) |
|
| 3 |
+ return if association.all? {|s| s[options[:with]] == record[options[:with]] }
|
|
| 4 |
+ record.errors[attribute] << "must be owned by you" |
|
| 5 |
+ end |
|
| 6 |
+end |
@@ -68,7 +68,7 @@ |
||
| 68 | 68 |
<%= f.select(:control_target_ids, |
| 69 | 69 |
options_for_select(current_user.agents.map {|s| [s.name, s.id] },
|
| 70 | 70 |
@agent.control_target_ids), |
| 71 |
- {}, { multiple: true, size: 5, class: 'select2 form-control' }) %>
|
|
| 71 |
+ {}, { multiple: true, size: 5, class: 'select2-linked-tags form-control', data: {url_prefix: '/agents'}}) %>
|
|
| 72 | 72 |
</div> |
| 73 | 73 |
</div> |
| 74 | 74 |
</div> |
@@ -83,12 +83,13 @@ |
||
| 83 | 83 |
|
| 84 | 84 |
<div class="form-group"> |
| 85 | 85 |
<%= f.label :sources %> |
| 86 |
+ <span class="glyphicon glyphicon-question-sign hover-help" data-content="This Agent will receive events from the selected Agents."></span> |
|
| 86 | 87 |
<div class="link-region" data-can-receive-events="<%= @agent.can_receive_events? %>"> |
| 87 | 88 |
<% eventSources = (current_user.agents - [@agent]).find_all { |a| a.can_create_events? } %>
|
| 88 | 89 |
<%= f.select(:source_ids, |
| 89 | 90 |
options_for_select(eventSources.map {|s| [s.name, s.id] },
|
| 90 | 91 |
@agent.source_ids), |
| 91 |
- {}, { :multiple => true, :size => 5, :class => 'select2 form-control' }) %>
|
|
| 92 |
+ {}, { :multiple => true, :size => 5, :class => 'select2-linked-tags form-control', data: {url_prefix: '/agents'} }) %>
|
|
| 92 | 93 |
<span class='cannot-receive-events text-info'>This type of Agent cannot receive events.</span> |
| 93 | 94 |
<%= f.label :propagate_immediately, :class => 'propagate-immediately' do %>Propagate immediately |
| 94 | 95 |
<%= f.check_box :propagate_immediately %> |
@@ -98,13 +99,26 @@ |
||
| 98 | 99 |
</div> |
| 99 | 100 |
</div> |
| 100 | 101 |
|
| 102 |
+ <div class="form-group"> |
|
| 103 |
+ <%= f.label :receivers %> |
|
| 104 |
+ <span class="glyphicon glyphicon-question-sign hover-help" data-content="Events created by this Agent will be sent to the selected Agents."></span> |
|
| 105 |
+ <div class="event-related-region"> |
|
| 106 |
+ <% eventTargets = (current_user.agents - [@agent]).find_all { |a| a.can_receive_events? } %>
|
|
| 107 |
+ <%= f.select(:receiver_ids, |
|
| 108 |
+ options_for_select(eventTargets.map {|s| [s.name, s.id] },
|
|
| 109 |
+ @agent.receiver_ids), |
|
| 110 |
+ {}, { :multiple => true, :size => 5, :class => 'select2-linked-tags form-control', data: {url_prefix: '/agents'} }) %>
|
|
| 111 |
+ <span class='cannot-create-events text-info'>This type of Agent cannot create events.</span> |
|
| 112 |
+ </div> |
|
| 113 |
+ </div> |
|
| 114 |
+ |
|
| 101 | 115 |
<% if current_user.scenario_count > 0 %> |
| 102 | 116 |
<div class="form-group"> |
| 103 | 117 |
<%= f.label :scenarios %> |
| 104 | 118 |
<span class="glyphicon glyphicon-question-sign hover-help" data-content="Use Scenarios to group sets of Agents, both for organization, and to make them easy to export and share."></span> |
| 105 | 119 |
<%= f.select(:scenario_ids, |
| 106 | 120 |
options_for_select(current_user.scenarios.pluck(:name, :id), @agent.scenario_ids), |
| 107 |
- {}, { :multiple => true, :size => 5, :class => 'select2 form-control' }) %>
|
|
| 121 |
+ {}, { :multiple => true, :size => 5, :class => 'select2-linked-tags form-control', data: {url_prefix: '/scenarios'} }) %>
|
|
| 108 | 122 |
</div> |
| 109 | 123 |
<% end %> |
| 110 | 124 |
|
@@ -53,7 +53,7 @@ |
||
| 53 | 53 |
<%= f.label :agents %> |
| 54 | 54 |
<%= f.select(:agent_ids, |
| 55 | 55 |
options_for_select(current_user.agents.pluck(:name, :id), @scenario.agent_ids), |
| 56 |
- {}, { :multiple => true, :size => 5, :class => 'select2 form-control' }) %>
|
|
| 56 |
+ {}, { :multiple => true, :size => 5, :class => 'select2-linked-tags form-control', data: {url_prefix: '/agents'} }) %>
|
|
| 57 | 57 |
</div> |
| 58 | 58 |
</div> |
| 59 | 59 |
</div> |
@@ -40,4 +40,4 @@ en: |
||
| 40 | 40 |
other: ">%{count}yr"
|
| 41 | 41 |
almost_x_years: |
| 42 | 42 |
one: "~1yr" |
| 43 |
- other: "~%{count}yr"
|
|
| 43 |
+ other: "~%{count}yr"
|
@@ -0,0 +1,9 @@ |
||
| 1 |
+if defined? RSpec |
|
| 2 |
+ namespace :spec do |
|
| 3 |
+ desc 'Run all specs in spec directory (exluding feature specs)' |
|
| 4 |
+ RSpec::Core::RakeTask.new(:nofeatures) do |task| |
|
| 5 |
+ ENV['RSPEC_TASK'] = 'spec:nofeatures' |
|
| 6 |
+ task.exclude_pattern = "spec/features/**/*_spec.rb" |
|
| 7 |
+ end |
|
| 8 |
+ end |
|
| 9 |
+end |
@@ -15,11 +15,19 @@ Capybara.default_max_wait_time = CAPYBARA_TIMEOUT |
||
| 15 | 15 |
RSpec.configure do |config| |
| 16 | 16 |
config.include Warden::Test::Helpers |
| 17 | 17 |
config.include AlertConfirmer, type: :feature |
| 18 |
- config.before :suite do |
|
| 18 |
+ |
|
| 19 |
+ config.before(:suite) do |
|
| 19 | 20 |
Warden.test_mode! |
| 21 |
+ DatabaseCleaner.clean_with(:truncation) |
|
| 22 |
+ end |
|
| 23 |
+ |
|
| 24 |
+ config.before(:each) do |example| |
|
| 25 |
+ DatabaseCleaner.strategy = example.metadata[:js] ? :truncation : :transaction |
|
| 26 |
+ DatabaseCleaner.start |
|
| 20 | 27 |
end |
| 21 | 28 |
|
| 22 |
- config.after :each do |
|
| 29 |
+ config.after(:each) do |
|
| 30 |
+ DatabaseCleaner.clean |
|
| 23 | 31 |
Warden.test_reset! |
| 24 | 32 |
end |
| 25 | 33 |
end |
@@ -203,6 +203,18 @@ describe AgentsController do |
||
| 203 | 203 |
expect(assigns(:agent)).to be_a(Agents::WebsiteAgent) |
| 204 | 204 |
end |
| 205 | 205 |
|
| 206 |
+ it "creates Agents and accepts specifing a target agent" do |
|
| 207 |
+ sign_in users(:bob) |
|
| 208 |
+ attributes = valid_attributes |
|
| 209 |
+ attributes[:receiver_ids] = attributes[:source_ids] |
|
| 210 |
+ expect {
|
|
| 211 |
+ expect {
|
|
| 212 |
+ post :create, :agent => attributes |
|
| 213 |
+ }.to change { users(:bob).agents.count }.by(1)
|
|
| 214 |
+ }.to change { Link.count }.by(2)
|
|
| 215 |
+ expect(assigns(:agent)).to be_a(Agents::WebsiteAgent) |
|
| 216 |
+ end |
|
| 217 |
+ |
|
| 206 | 218 |
it "shows errors" do |
| 207 | 219 |
sign_in users(:bob) |
| 208 | 220 |
expect {
|
@@ -1,4 +1,4 @@ |
||
| 1 |
-require 'capybara_helper' |
|
| 1 |
+require 'rails_helper' |
|
| 2 | 2 |
|
| 3 | 3 |
describe Admin::UsersController do |
| 4 | 4 |
it "requires to be signed in as an admin" do |
@@ -1,8 +1,11 @@ |
||
| 1 |
-require 'capybara_helper' |
|
| 1 |
+require 'rails_helper' |
|
| 2 | 2 |
|
| 3 | 3 |
describe "Creating a new agent", js: true do |
| 4 |
- it "creates an agent" do |
|
| 4 |
+ before(:each) do |
|
| 5 | 5 |
login_as(users(:bob)) |
| 6 |
+ end |
|
| 7 |
+ |
|
| 8 |
+ it "creates an agent" do |
|
| 6 | 9 |
visit "/" |
| 7 | 10 |
page.find("a", text: "Agents").trigger(:mouseover)
|
| 8 | 11 |
click_on("New Agent")
|
@@ -15,7 +18,6 @@ describe "Creating a new agent", js: true do |
||
| 15 | 18 |
end |
| 16 | 19 |
|
| 17 | 20 |
it "creates an alert if a new agent with invalid json is submitted" do |
| 18 |
- login_as(users(:bob)) |
|
| 19 | 21 |
visit "/" |
| 20 | 22 |
page.find("a", text: "Agents").trigger(:mouseover)
|
| 21 | 23 |
click_on("New Agent")
|
@@ -30,4 +32,67 @@ describe "Creating a new agent", js: true do |
||
| 30 | 32 |
}') |
| 31 | 33 |
expect(get_alert_text_from { click_on "Save" }).to have_text("Sorry, there appears to be an error in your JSON input. Please fix it before continuing.")
|
| 32 | 34 |
end |
| 35 |
+ |
|
| 36 |
+ context "displaying the correct information" do |
|
| 37 |
+ before(:each) do |
|
| 38 |
+ visit new_agent_path |
|
| 39 |
+ end |
|
| 40 |
+ it "shows all options for agents that can be scheduled, create and receive events" do |
|
| 41 |
+ select2("Website Agent", from: "Type")
|
|
| 42 |
+ expect(page).not_to have_content('This type of Agent cannot create events.')
|
|
| 43 |
+ end |
|
| 44 |
+ |
|
| 45 |
+ it "does not show the target select2 field when the agent can not create events" do |
|
| 46 |
+ select2("Growl Agent", from: "Type")
|
|
| 47 |
+ expect(page).to have_content('This type of Agent cannot create events.')
|
|
| 48 |
+ end |
|
| 49 |
+ end |
|
| 50 |
+ |
|
| 51 |
+ it "allows to click on on the agent name in select2 tags" do |
|
| 52 |
+ agent = agents(:bob_weather_agent) |
|
| 53 |
+ visit new_agent_path |
|
| 54 |
+ select2("Website Agent", from: "Type")
|
|
| 55 |
+ select2("SF Weather", from: 'Sources')
|
|
| 56 |
+ click_on "SF Weather" |
|
| 57 |
+ expect(page).to have_content "Editing your WeatherAgent" |
|
| 58 |
+ end |
|
| 59 |
+ |
|
| 60 |
+ context "clearing unsupported fields of agents" do |
|
| 61 |
+ before do |
|
| 62 |
+ visit new_agent_path |
|
| 63 |
+ end |
|
| 64 |
+ |
|
| 65 |
+ it "does not send previously configured sources when the current agent does not support them" do |
|
| 66 |
+ select2("Website Agent", from: "Type")
|
|
| 67 |
+ select2("SF Weather", from: 'Sources')
|
|
| 68 |
+ select2("Webhook Agent", from: "Type")
|
|
| 69 |
+ fill_in(:agent_name, with: "No sources") |
|
| 70 |
+ click_on "Save" |
|
| 71 |
+ expect(page).to have_content("No sources")
|
|
| 72 |
+ agent = Agent.find_by(name: "No sources") |
|
| 73 |
+ expect(agent.sources).to eq([]) |
|
| 74 |
+ end |
|
| 75 |
+ |
|
| 76 |
+ it "does not send previously configured control targets when the current agent does not support them" do |
|
| 77 |
+ select2("Commander Agent", from: "Type")
|
|
| 78 |
+ select2("SF Weather", from: 'Control targets')
|
|
| 79 |
+ select2("Webhook Agent", from: "Type")
|
|
| 80 |
+ fill_in(:agent_name, with: "No control targets") |
|
| 81 |
+ click_on "Save" |
|
| 82 |
+ expect(page).to have_content("No control targets")
|
|
| 83 |
+ agent = Agent.find_by(name: "No control targets") |
|
| 84 |
+ expect(agent.control_targets).to eq([]) |
|
| 85 |
+ end |
|
| 86 |
+ |
|
| 87 |
+ it "does not send previously configured receivers when the current agent does not support them" do |
|
| 88 |
+ select2("Website Agent", from: "Type")
|
|
| 89 |
+ select2("ZKCD", from: 'Receivers')
|
|
| 90 |
+ select2("Email Agent", from: "Type")
|
|
| 91 |
+ fill_in(:agent_name, with: "No receivers") |
|
| 92 |
+ click_on "Save" |
|
| 93 |
+ expect(page).to have_content("No receivers")
|
|
| 94 |
+ agent = Agent.find_by(name: "No receivers") |
|
| 95 |
+ expect(agent.receivers).to eq([]) |
|
| 96 |
+ end |
|
| 97 |
+ end |
|
| 33 | 98 |
end |
@@ -1,4 +1,4 @@ |
||
| 1 |
-require 'capybara_helper' |
|
| 1 |
+require 'rails_helper' |
|
| 2 | 2 |
|
| 3 | 3 |
describe "Editing an agent", js: true do |
| 4 | 4 |
it "creates an alert if a agent with invalid json is submitted" do |
@@ -38,7 +38,7 @@ bob_disabled_website_agent: |
||
| 38 | 38 |
user: bob |
| 39 | 39 |
events_count: 1 |
| 40 | 40 |
schedule: "midnight" |
| 41 |
- name: "Disabled ZKCD" |
|
| 41 |
+ name: "Disabled Agent" |
|
| 42 | 42 |
guid: <%= SecureRandom.hex %> |
| 43 | 43 |
options: <%= {
|
| 44 | 44 |
:url => "http://xkcd.com", |
@@ -51,6 +51,8 @@ describe DotHelper do |
||
| 51 | 51 |
agent.save! |
| 52 | 52 |
}, |
| 53 | 53 |
] |
| 54 |
+ @foo.reload |
|
| 55 |
+ @bar2.reload |
|
| 54 | 56 |
end |
| 55 | 57 |
|
| 56 | 58 |
it "generates a DOT script" do |
@@ -546,6 +546,17 @@ describe Agent do |
||
| 546 | 546 |
expect(agent).to have(0).errors_on(:sources) |
| 547 | 547 |
end |
| 548 | 548 |
|
| 549 |
+ it "should not allow target agents owned by other people" do |
|
| 550 |
+ agent = Agents::SomethingSource.new(:name => "something") |
|
| 551 |
+ agent.user = users(:bob) |
|
| 552 |
+ agent.receiver_ids = [agents(:bob_weather_agent).id] |
|
| 553 |
+ expect(agent).to have(0).errors_on(:receivers) |
|
| 554 |
+ agent.receiver_ids = [agents(:jane_weather_agent).id] |
|
| 555 |
+ expect(agent).to have(1).errors_on(:receivers) |
|
| 556 |
+ agent.user = users(:jane) |
|
| 557 |
+ expect(agent).to have(0).errors_on(:receivers) |
|
| 558 |
+ end |
|
| 559 |
+ |
|
| 549 | 560 |
it "should not allow controller agents owned by other people" do |
| 550 | 561 |
agent = Agents::SomethingSource.new(:name => "something") |
| 551 | 562 |
agent.user = users(:bob) |
@@ -961,6 +972,8 @@ describe AgentDrop do |
||
| 961 | 972 |
@efa.sources << @wsa1 << @wsa2 |
| 962 | 973 |
@efa.memory[:test] = 1 |
| 963 | 974 |
@efa.save! |
| 975 |
+ @wsa1.reload |
|
| 976 |
+ @wsa2.reload |
|
| 964 | 977 |
end |
| 965 | 978 |
|
| 966 | 979 |
it 'should be created via Agent#to_liquid' do |
@@ -38,7 +38,7 @@ RSpec.configure do |config| |
||
| 38 | 38 |
# If you're not using ActiveRecord, or you'd prefer not to run each of your |
| 39 | 39 |
# examples within a transaction, remove the following line or assign false |
| 40 | 40 |
# instead of true. |
| 41 |
- config.use_transactional_fixtures = true |
|
| 41 |
+ config.use_transactional_fixtures = ENV['RSPEC_TASK'] == 'spec:nofeatures' |
|
| 42 | 42 |
|
| 43 | 43 |
# rspec-rails 3 will no longer automatically infer an example group's spec type |
| 44 | 44 |
# from the file location. You can explicitly opt-in to this feature using this |
@@ -70,3 +70,7 @@ RSpec.configure do |config| |
||
| 70 | 70 |
config.include SpecHelpers |
| 71 | 71 |
config.include Delorean |
| 72 | 72 |
end |
| 73 |
+ |
|
| 74 |
+if ENV['RSPEC_TASK'] != 'spec:nofeatures' |
|
| 75 |
+ require 'capybara_helper' |
|
| 76 |
+end |